﻿/* ==============================================================================
 * 功能描述：UIManager  
 * 
 * 创 建 者：郑镇泉
 * 
 * 创建日期：2016/4/3 23:34:35
 * ==============================================================================*/

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;

namespace ZZQFrameWork
{
    public class UIManager : Singleton<UIManager>
    {
        #region UI管理

        /// <summary>
        /// UI信息
        /// </summary>
        public class UIInfo
        {
            /// <summary>
            /// UI名称
            /// </summary>
            public string uiName;

            /// <summary>
            /// UI类型
            /// </summary>
            public Enum_UIType uiType;

            /// <summary>
            /// UI脚本
            /// </summary>
            public Type scriptType;

            /// <summary>
            /// 可变参数
            /// </summary>
            public object[] uiParams;

            public UIInfo(Enum_UIType type, params object[] objects)
            {
                uiType = type;
                uiName = UIDef.GetUINameByUIType(type);
                scriptType = UIDef.GetUIScriptByUIType(type);
                uiParams = objects;
            }
        }

        /// <summary>
        /// 已经拥有的UI集合，曾经打开过还未彻底删除的UI
        /// </summary>
        public Dictionary<Enum_UIType, GameObject> hasUIDic = null; 

        /// <summary>
        /// 已经打开的UI集合
        /// </summary>
        public Dictionary<Enum_UIType, GameObject> openUIDic = null;

        /// <summary>
        /// 需要打开的UI集合
        /// </summary>
        public Stack<UIInfo> waitUIStack = null;

        /// <summary>
        /// 所有panel的容器
        /// </summary>
        private Transform uiContainer;

        public Transform UIContainer
        {
            get
            {
                if (uiContainer == null)
                {
                    GameObject go = GameObject.Find("RootUI");
                    if (go == null)
                    {
                        go = GameObject.Instantiate(ResManager.Instance.Load("RootUI") as GameObject);
                    }
                    uiContainer = go.transform.Find("UICamera/ScreenAdaptor/Canvas/Container");
                }
                return uiContainer;
            }
        }

        protected override void Init()
        {
            openUIDic = new Dictionary<Enum_UIType, GameObject>();
            hasUIDic=new Dictionary<Enum_UIType, GameObject>();
            waitUIStack = new Stack<UIInfo>();
        }

        #region 根据UI类型获取UI信息

        /// <summary>
        /// 根据ui类型获取UI物体
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public GameObject GetUIGameObjectByUIType(Enum_UIType type)
        {
            if (openUIDic.ContainsKey(type))
            {
                return openUIDic[type];
            }
            return null;
        }

        /// <summary>
        /// 根据UI类型获取UI上的baseUI
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <returns></returns>
        public T GetTByUIType<T>(Enum_UIType type) where T : BaseUI
        {
            T t = null;
            if (openUIDic.ContainsKey(type))
            {
                t = openUIDic[type].GetComponent<T>();
                if (t == null)
                {
                    Debug.LogError("not find T,type:" + type);
                }
                else
                {
                    return t;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取需要的类型UI
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public GameObject GetNeedUIByUIType(Enum_UIType type)
        {
            if (hasUIDic.ContainsKey(type))
            {
                return hasUIDic[type];
            }
            return null;
        }

        #endregion

        #region 准备开启UI

        public void OpenUI(Enum_UIOpenType openType, Enum_UIType uiType)
        {
            OpenUI(openType, uiType, null);
        }

        public void OpenUI(Enum_UIOpenType openType, Enum_UIType uiType, params object[] objects)
        {
            Enum_UIType[] types = new Enum_UIType[1];
            types[0] = uiType;
            OpenUI(openType, types, objects);
        }

        public void OpenUI(Enum_UIOpenType openType, Enum_UIType[] uiTypes)
        {
            OpenUI(openType, uiTypes, null);
        }

        /// <summary>
        /// 准备开启UI
        /// </summary>
        /// <param name="openType">UI开启类型</param>
        /// <param name="uiTypes">需要开启的UI集合</param>
        /// <param name="objects">可变参数</param>
        public void OpenUI(Enum_UIOpenType openType, Enum_UIType[] uiTypes, params object[] objects)
        {
            Debug.Log("准备打开UI");
            ExecuteByOpenType(openType);

            for (int i = 0; i < uiTypes.Length; i++)
            {
                if (!openUIDic.ContainsKey(uiTypes[i]))
                {
                    UIInfo info = new UIInfo(uiTypes[i], objects);
                    waitUIStack.Push(info);
                }
            }

            if (waitUIStack.Count > 0)
            {
                OpenUI();
            }
        }

        #endregion

        /// <summary>
        /// 根据UI开启的类型执行
        /// </summary>
        /// <param name="type"></param>
        private void ExecuteByOpenType(Enum_UIOpenType type)
        {
            switch (type)
            {
                case Enum_UIOpenType.CloseOthers:
                    CloseAllUI();
                    break;
                //case Enum_UIOpenType.OpenSelf:
                //    CloseAllUI();
                //    break;
            }
        }

        /// <summary>
        /// 创建开启UI
        /// </summary>
        private void OpenUI()
        {
            //根据等待打开的UI集合数量打开所有的UI
            for (int i = 0; i < waitUIStack.Count; i++)
            {
                UIInfo info = waitUIStack.Pop();
                GameObject go = GetNeedUIByUIType(info.uiType);
                if (go == null)
                {
                    go = GameObject.Instantiate(ResManager.Instance.Load(info.uiName) as GameObject);
                    go.transform.SetParent(UIContainer, false);
                    hasUIDic.Add(info.uiType,go);
                }
                BaseUI baseUI = go.GetComponent<BaseUI>();
                if (baseUI == null)
                {
                    baseUI = go.AddComponent(info.scriptType) as BaseUI;
                }
                baseUI.Open(info.uiParams);
                openUIDic.Add(info.uiType, go);
            }
        }

        /// <summary>
        /// 关闭UI
        /// </summary>
        public void CloseUI(Enum_UIType type)
        {
            GameObject go = GetUIGameObjectByUIType(type);
            go.GetComponent<BaseUI>().Close();
            openUIDic.Remove(type);
        }

        /// <summary>
        /// 关闭所有UI
        /// </summary>
        public void CloseAllUI()
        {
            if(openUIDic.Count<=0)return;
            foreach (KeyValuePair<Enum_UIType, GameObject> keyValuePair in openUIDic)
            {
                keyValuePair.Value.GetComponent<BaseUI>().Close();
            }
            openUIDic.Clear();
        }

        #endregion

        #region MessageBox管理

        /// <summary>
        /// 消息框
        /// </summary>
        private MessageBox messageBox;

        public MessageBox MessageBox
        {
            get
            {
                if (messageBox == null)
                {
                    GameObject go = GameObject.Instantiate(ResManager.Instance.Load("MessageBox") as GameObject);
                    RectTransform rt = go.AddComponent<RectTransform>();
                    rt.SetParent(UIContainer, false);
                    rt.SetAsLastSibling();
                    messageBox = go.GetOrAddComponent<MessageBox>();
                }
                return messageBox;
            }
        }

        /// <summary>
        /// 显示消息框
        /// </summary>
        /// <param name="title">消息的标题</param>
        /// <param name="content">消息的内容</param>
        public void ShowMessageBox(string title, string content)
        {
            MessageBox.SetTitle(title);
            MessageBox.SetContent(content);
            MessageBox.Show();
        }

        /// <summary>
        /// 关闭消息框
        /// </summary>
        public void CloseMessageBox()
        {
            MessageBox.Hide();
        }

        #endregion

        #region HUD管理

        /// <summary>
        /// HUD预设
        /// </summary>
        private GameObject hudPrefab;

        public GameObject HUDPrefab
        {
            get
            {
                if (hudPrefab == null)
                {
                    hudPrefab = ResManager.Instance.Load("HUDItem") as GameObject;
                }
                return hudPrefab;
            }
        }

        /// <summary>
        /// 正在使用的集合
        /// </summary>
        public List<HUDItem> useList = new List<HUDItem>();

        /// <summary>
        /// 没有使用的集合
        /// </summary>
        public List<HUDItem> unUseList = new List<HUDItem>();

        #region 飘字重载方法

        public void ShowHUD(string content, float time)
        {
            ShowHUD(content, Color.green, time, 20, Color.black, Color.black);
        }

        public void ShowHUD(string content, Color contentColor, float time)
        {
            ShowHUD(content, contentColor, time, 20, Color.black, Color.black);
        }

        public void ShowHUD(string content, Color contentColor, float time, int contentSize)
        {
            ShowHUD(content, contentColor, time, contentSize, Color.black, Color.black);
        }

        public void ShowHUD(string content, Color contentColor, float time, int contentSize, Color outlineColor)
        {
            ShowHUD(content, contentColor, time, contentSize, outlineColor, Color.black);
        }

        public void ShowHUD(string content, Color contentColor, float time,Vector3 endPos)
        {
            ShowHUD(Vector3.zero, content, contentColor, time, 20, Color.black, Color.black,endPos);
        }

        public void ShowHUD(string content, Color contentColor, float time, int contentSize, Color outlineColor,
            Color shadowColor)
        {
            ShowHUD(Vector3.zero, content, contentColor, time, contentSize, outlineColor, Color.black,Vector3.zero);
        }

        public void ShowHUD(Vector3 startPos, string content, float time)
        {
            ShowHUD(startPos, content, Color.green, time, 20, Color.black, Color.black,Vector3.zero);
        }

        public void ShowHUD(Vector3 startPos, string content, Color contentColor, float time)
        {
            ShowHUD(startPos, content, contentColor, time, 20, Color.black, Color.black,Vector3.zero);
        }

        public void ShowHUD(Vector3 startPos, string content, Color contentColor, float time, int contentSize)
        {
            ShowHUD(startPos, content, contentColor, time, contentSize, Color.black, Color.black,Vector3.zero);
        }

        public void ShowHUD(Vector3 startPos, string content, Color contentColor, float time, int contentSize,
            Color outlineColor)
        {
            ShowHUD(startPos, content, contentColor, time, contentSize, outlineColor, Color.black,Vector3.zero);
        }

        public void ShowHUD(Vector3 startPos, string content, Color contentColor, float time, int contentSize,
    Color outlineColor,Vector3 endPos)
        {
            ShowHUD(startPos, content, contentColor, time, contentSize, outlineColor, Color.black,endPos);
        }

        #endregion

        /// <summary>
        /// 显示HUD飘字
        /// </summary>
        /// <param name="startPos">开始的坐标</param>
        /// <param name="content">显示的内容</param>
        /// <param name="contentColor">内容的颜色</param>
        /// <param name="time">显示的时间</param>
        /// <param name="contentSize">内容字体的大小</param>
        /// <param name="outlineColor">描边的颜色</param>
        /// <param name="shadowColor">阴影的颜色</param>
        /// <param name="endPos">需要移动到的点</param>
        public void ShowHUD(Vector3 startPos, string content, Color contentColor, float time, int contentSize, Color outlineColor, Color shadowColor, Vector3 endPos)
        {
            HUDItem item = GetHUDItem();
            item.SetPosition(startPos);
            item.SetContent(content);
            item.SetContentColor(contentColor);
            item.SetFontSize(contentSize);
            item.SetOutlineColor(outlineColor);
            item.SetShadowColor(shadowColor);

            Move(item,time,endPos);
        }

        /// <summary>
        /// 获取一个HUDItem，如果在未使用集合中有，则取出，否则新创建
        /// </summary>
        /// <returns></returns>
        private HUDItem GetHUDItem()
        {
            HUDItem item;
            if (unUseList.Count > 0)
            {
                item = unUseList[0];
                item.transform.localPosition=Vector3.zero;
                item.gameObject.SetActive(true);
                unUseList.Remove(item);
            }
            else
            {
                GameObject go = GameObject.Instantiate(HUDPrefab);
                go.transform.SetParent(UIContainer,false);
                go.transform.localPosition=Vector3.zero;
                item = go.GetComponent<HUDItem>();
            }
            useList.Add(item);
            return item;
        }

        /// <summary>
        /// 飘字移动
        /// </summary>
        /// <param name="item"></param>
        /// <param name="time"></param>
        private void Move(HUDItem item,float time,Vector3 endPos)
        {
            if (endPos == Vector3.zero) endPos = item.transform.localPosition+Vector3.up * 100;
            Tweener tweener = item.transform.DOLocalMove(endPos, time);
            tweener.OnComplete(() =>
            {
                useList.Remove(item);
                unUseList.Add(item);
                item.gameObject.SetActive(false);
                tweener.Kill();
            });
        }

        #endregion

        #region Tips管理

        private TipsPanel tipsPanel;

        public TipsPanel TipsPanel
        {
            get
            {
                if (tipsPanel == null)
                {
                    GameObject go = GameObject.Find("TipsPanel");
                    if (go == null)
                    {
                        go=GameObject.Instantiate(ResManager.Instance.Load("TipsPanel")as GameObject);
                        go.transform.SetParent(UIContainer,false);
                    }
                    tipsPanel = go.GetComponent<TipsPanel>();
                }
                return tipsPanel;
            }
        }

        public void ShowTips(GoodsVO goods)
        {
            TipsPanel.Show(goods);
        }

        public void HideTips()
        {
            TipsPanel.Hide();
        }

        #endregion

    }
}
